import React, {Component} from 'react';
import Markdown from 'react-markdown';
import {Anchor, Row, Col} from 'antd';

const {Link} = Anchor;

class JsPage extends Component {
    constructor(props) {
        super(props);
    }

    render() {

        return (
            <div style={{background:"#c0d2bc"}}>
                <Row>
                    <Col span={19}>





                        <h3 id="spi"> JAVA的SPI机制 </h3>
                        <Markdown source={
                        "SPI的英文全称为Service Provider Interface，字面意思为服务提供者接口，它是jdk提供给“服务提供厂商”或者“插件开发者”使用的接口。\n\n" +
                        "在面向对象的设计中，模块之间我们一般会采取面向接口编程的方式，而在实际编程过程过程中，api的实现是封装在jar中，当我们想要换一种实现方法时，还要生成新的jar替换以前的实现类。而通过jdk的SPI机制就可以实现，不修改原来jar的情况下，为api新增一种实现。\n\n" +
                        "总结一下SPI的思想：在系统的各个模块中，往往有不同的实现方案，例如日志模块的方案、xml解析的方案等，为了在装载模块的时候不具体指明实现类，我们需要一种服务发现机制，java spi就提供这样一种机制。有点类似于ioc的思想，将服务装配的控制权移到程序之外，在模块化设计时尤其重要。\n\n" +
                        "### API和SPI的区别\n\n" +
                        "API：提供给调用方，完成某项功能的接口（类、或者方法），你可以使用它完成任务。例如xxService.updateXX提供了修改的功能，在api内部封装了修改订单价格的逻辑，你只需要调用该接口，即可实现修改订单价格。\n\n" +
                        "SPI：是一种callback的思想，在一些通用的标准中（即API），为实现厂商提供扩展点。当API被调用时，会动态加载SPI路由到特定的实现中。例如xxService.updateXX的年龄校验逻辑作为扩展点（即SPI），年龄不能超过65...\n\n" +
                        "### Java SPI的具体运用场景\n\n" +
                        "案例一：java.sql.Driver的spi实现，有mysql驱动、oracle驱动等。以mysql为例，实现类是com.mysql.jdbc.Driver，在mysql-connector-java-5.1.6.jar中，我们可以看到有一个META-INF/services目录，目录下有一个文件名为java.sql.Driver的文件，其中的内容是com.mysql.jdbc.Driver。\n\n" +
                        "案例二：common-logging的日志接口实现。apache最早只提供了日志的门面接口，没有实现。具体方案由各提供商实现， 发现日志提供商是通过扫描 META-INF/services/org.apache.commons.logging.LogFactory配置文件，通过读取该文件的内容找到日志提工商实现类。只要我们的日志实现里包含了这个文件，并在文件里制定 LogFactory工厂接口的实现类即可。\n\n" +
                        "### Java SPI的简单示例\n\n" +
                        "实现加法的spi\n\n" +
                        "    package com.demo.api.impl;\n" +
                        "    import com.demo.api.INumOperate;\n" +
                        "    /**\n" +
                        "     * 数字相加\n" +
                        "     */\n" +
                        "    public class NumPlusOperateImpl implements INumOperate {\n" +
                        "        @Override\n" +
                        "        public int operator(int a, int b) {\n" +
                        "            int r = a + b;\n" +
                        "            System.out.println(\"(SPI机制)加法，结果：\" + r);\n" +
                        "            return r;\n" +
                        "        }\n" +
                        "    }\n\n" +
                        "实现乘法的spi\n\n" +
                        "    package com.demo.spi.impl;\n" +
                        "    import com.demo.api.INumOperate;\n" +
                        "    /**\n" +
                        "     * 数字相乘\n" +
                        "     */\n" +
                        "    public class NumMutliOperateImpl implements INumOperate {\n" +
                        "        @Override\n" +
                        "        public int operator(int a, int b) {\n" +
                        "            int r = a * b;\n" +
                        "            System.out.println(\"(SPI机制)乘法，结果：\" + r);\n" +
                        "            return r;\n" +
                        "        }\n" +
                        "    }\n\n" +
                        "在META-INFO/services目录下（如果没有改目录，手工新建即可），新建一个以com.demo.api.INumOperate命名的文件，文件内容指明两个SPI的实现类的权限定名称，如下：\n\n" +
                        "    com.demo.spi.impl.NumMutliOperateImpl\n" +
                        "    com.demo.spi.impl.NumPlusOperateImpl\n\n" +
                        "main函数如下，主程序中没有显示指明spi的实现，而是通过ServiceLoader动态加载实现类：\n\n" +
                        "import java.util.Iterator;\n" +
                        "    import java.util.ServiceLoader;\n" +
                        "    import com.demo.api.INumOperate;\n" +
                        "    import com.demo.api.impl.NumPlusOperateImpl;\n" +
                        "    \n" +
                        "    public class Main {\n" +
                        "        public static void main(String[] args) {\n" +
                        "            int a = 9;\n" +
                        "            int b = 3;\n" +
                        "            // SPI机制，寻找所有的实现类，顺序执行\n" +
                        "            ServiceLoader<INumOperate> loader = ServiceLoader.load(INumOperate.class); // 查找SPI实现类，并加载到jvm\n" +
                        "            Iterator<INumOperate> iter = loader.iterator();\n" +
                        "            while (iter.hasNext()) {\n" +
                        "                INumOperate op = iter.next();\n" +
                        "                op.operator(a, b);\n" +
                        "            }\n" +
                        "        }\n" +
                        "    }\n\n" +
                        "程序的运行结果如下：\n\n" +
                        "(SPI机制)乘法，结果：27\n\n" +
                        "(SPI机制)加法，结果：12"}/>


                    </Col>
                    <Col span={5}>

                    </Col>
                </Row>
            </div>

        );
    }
}

export default JsPage;